//`define DRIV_IF vif.DRIVER.driver_cb

class axi_lite_driver extends uvm_driver #(axi_lite_seq_item);

  //--------------------------------------- 
  // Virtual Interface
  //--------------------------------------- 
  virtual axi_lite_interface vif;
  `uvm_component_utils(axi_lite_driver)
    
  //--------------------------------------- 
  // Constructor
  //--------------------------------------- 
  function new (string name, uvm_component parent);
    super.new(name, parent);
  endfunction : new

  //--------------------------------------- 
  // build phase
  //---------------------------------------
  function void build_phase(uvm_phase phase);
    super.build_phase(phase);
     if(!uvm_config_db#(virtual axi_lite_interface)::get(this, "", "vif", vif))
       `uvm_fatal("NO_VIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
  endfunction: build_phase

  //---------------------------------------  
  // run phase
  //---------------------------------------  
  virtual task run_phase(uvm_phase phase);
    forever begin
      seq_item_port.get_next_item(req);
      drive();
      seq_item_port.item_done();
    end
  endtask : run_phase
  
  //---------------------------------------
  // drive - transaction level to signal level
  // drives the value's from seq_item to interface signals
  
  virtual task drive();
             
    @(posedge vif.aclk_i);
    //@(posedge vif.aclk_i);
      
    wait(vif.areset_n_i == 1);
	
	vif.write_addrv_i  <= 0  ;
	vif.write_datav_i  <= 0  ;
	@(posedge vif.aclk_i);
        
    //if(req.write_start_i) begin
	/* 
	vif.write_addr_i   <= req.write_addr_i  ; 
	vif.write_addrv_i  <= req.write_addrv_i  ; 
	vif.write_data_i   <= req.write_data_i  ; 
	vif.write_datav_i  <= req.write_datav_i  ;
	vif.write_strb_i   <= req.write_strb_i  ;
	@(posedge vif.aclk_i);
	vif.write_addrv_i  <= 0  ;
	//vif.write_data_i   <= req.write_data_i  ; 
	vif.write_datav_i  <= 0  ;
	//vif.write_strb_i   <= req.write_strb_i  ;  
	@(posedge vif.aclk_i);
	req.write_bresp_o  <= vif.write_bresp_o ; 
    req.write_bvalid_o <= vif.write_bvalid_o;    */    
    //vif.write_addrv_i  <= 0  ;
    // vif.write_datav_i  <= 0  ;
	
	vif.write_addr_i   <= req.write_addr_i  ; 
	vif.write_addrv_i  <= req.write_addrv_i  ; 
	
	@(posedge vif.aclk_i);
	vif.write_addrv_i  <= 0  ;
	vif.write_data_i   <= req.write_data_i  ; 
	vif.write_datav_i  <= req.write_datav_i  ;
	vif.write_strb_i   <= req.write_strb_i  ;
	
	@(posedge vif.aclk_i);
	vif.write_datav_i  <= 0  ;
	
	//@(posedge vif.aclk_i);
	req.write_bresp_o  = vif.write_bresp_o ; 
    req.write_bvalid_o = vif.write_bvalid_o;   
    
  //Read Transaction Logic 
    @(posedge vif.aclk_i);
    
      //$display("driver.. req.read_start_i = %d",req.read_start_i);
    if(req.read_start_i) begin
       
    vif.read_start_i    <= req.read_start_i;
    vif.read_addr_i     <= req.read_addr_i;
    vif.read_af_i       <= req.read_af_i;
	
	@(posedge vif.aclk_i);
	vif.read_start_i    <= 1'b0;
	
    //$display("read_driver=%0h",req.read_length_i);  

    wait(vif.read_datav_o);
      
    req.read_data_o   =  vif.read_data_o;
    req.read_datav_o  =  vif.read_datav_o;
    end  
     // $display("2vif.read_data_o = %h",vif.read_data_o);
  endtask : drive
endclass : axi_lite_driver